package com.bluegalaxy.nhb.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bluegalaxy.nhb.core.XxSqlQueryJoin;
import com.bluegalaxy.nhb.domain.constant.SqlKeyConst;
import com.bluegalaxy.nhb.domain.constant.XxBuildConst;
import com.bluegalaxy.nhb.domain.enums.SqlOperEnum;
import com.bluegalaxy.nhb.service.AnalyseSqlService;
import com.bluegalaxy.nhb.sql.AssembleSql;
import com.bluegalaxy.nhb.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * @author:
 * @date: 2021/8/14 12:59
 * @description:
 */
@Service("AnalyseSqlService")
public class AnalyseSqlServiceImpl implements AnalyseSqlService {

    private static Log log = LogFactory.getLog(AnalyseSqlServiceImpl.class);

    private static final String userAttributes = "userAttributes";  //用户属性

    private static final String m_keep = "keep";  // 留存
    private static final String m_funnel = "funnel";  // 漏斗
    private static final String m_event = "event";  // 事件
    private static final String m_overview = "overview";  // 基础指标
    private static final String m_spread = "spread";  // 分布

    /*********************用户画像各条件参数KEY***********************************************/
    private static String type = "type";
    private static String global_relation_key = "globalStr";  //key and/or
    private static String attribute_relation_key = "attributeStr";  //key and/or
    private static String action_relation_key = "actionStr";  //key and/or
    private static String order_relation_key = "orderStr";  //key and/or
    private static String and_value = "且";
    private static String or_value = "或";
    //用户属性
    private static String field_key = "attributeName";
    private static String function_key = "valueExpression";
    private static String params_key = "value1Str";
    private static String params2_key = "value2Str";
    private static String eventItemCode = "eventItemCode";

    //用户行为满足/行为序列
    private static String dataRange = "dataRange";

    private static String doThings = "doThings";
    private static String eventType = "eventType";

    private static String children = "eventItems";
    private static String e_eventItem = "eventItem";

    private static String e_field_key = "eventType";
    private static String e_function_key = "eventItemExpression";
    private static String e_params_key = "value1Str";
    private static String e_params2_key = "value2Str";

    private static String s_f_time = "time"; //ck sql字段，sql_filed_time
    private static String s_f_enent = "event"; //ck sql字段

    private static String table_events = "events"; //ck events表
    private static String table_users = "users"; //ck users表
    private static String events_alias = "e"; //ck users表
    private static String users_alias = "u"; //ck users表

    private static String relation_id = "e.login_id = u.login_id"; //关联id字段

    private static String distinct_id = "distinct_id";

    @Override
    public String analyseSql(JSONObject json, String paramModule,String funcType){
        if (json == null){
            return "";
        }
//        log.info("json:"+json.toJSONString());
        String globalRelation = json.containsKey(global_relation_key)?SqlOperEnum.getValue(json.getString(global_relation_key)):"";
        if (StringUtil.isEmpty(globalRelation)) globalRelation = SqlKeyConst.AND.toLowerCase();

        XxSqlQueryJoin xxSql = XxSqlQueryJoin.start();
        switch (paramModule){
            case m_keep:
                assemleCommon(funcType,json,globalRelation, xxSql);
                break;
            case m_funnel:
                assemleCommon(funcType,json,globalRelation, xxSql);
                break;
            case m_event:
                assemleCommon(funcType,json,globalRelation, xxSql);
                break;
            case m_overview:
                assemleCommon(funcType,json,globalRelation, xxSql);
                break;
            case m_spread:
                assemleCommon(funcType,json,globalRelation, xxSql);
                break;

            default:
                assemleCommon(funcType,json,globalRelation, xxSql);
        }

        String querySql = xxSql.end().getSql();
        log.info("querySql:"+querySql);
        return querySql;
    }

    private void assemleCommon(String funcType,JSONObject param,String relation,XxSqlQueryJoin xxSql){
        JSONArray jsonArray = param.getJSONArray(funcType);
        if (Objects.isNull(jsonArray) || jsonArray.isEmpty()){
            return;
        }

        boolean userSqlFlag = true;
        for(int i=0;i<jsonArray.size();i++) {
            JSONObject item = jsonArray.getJSONObject(i);
            JSONObject eventItem = item.getJSONObject(e_eventItem);

            String functionValue;
            String filed;
            if (userAttributes.equals(funcType)){
                filed = item.getString(field_key);
                functionValue = item.getString(function_key);
            }else{
                filed = eventItem.getString(eventItemCode);
                functionValue = item.getString(e_function_key);
            }
            Object filedValue = item.get(params_key);
            if (!checkCondition(filed,functionValue,filedValue)){
                continue;
            }
            if (userAttributes.equals(funcType) && userSqlFlag){
                xxSql.text(" and e.login_id").text(" in ( ");
                xxSql.select("u.login_id").from(table_users).text(" u ").where(" 1=1 ");
            }

            if (SqlKeyConst.BETWEEN.equals(functionValue)){
                AssembleSql.assemleBetween(filed,
                        relation+AssembleSql.capture(SqlKeyConst.BETWEEN),
                        item.get(params_key),item.get(params2_key),xxSql);
            }else if(functionValue.contains(SqlKeyConst.IN)){
                AssembleSql.assemleIn(filed,
                        relation+AssembleSql.capture(SqlOperEnum.getValue(functionValue)),
                        item.get(params_key),xxSql);
            }else {
                AssembleSql.assemle(filed,
                        relation+AssembleSql.capture(SqlOperEnum.getValue(functionValue)),
                        item.get(params_key),xxSql);
            }
            if (userAttributes.equals(funcType) && userSqlFlag){
                userSqlFlag = false;
                xxSql.text(")");
            }
        }


    }



    private boolean checkCondition(String field,String expression,Object fieldValue){
        if (StringUtil.isEmpty(field) || StringUtil.isEmpty(expression) ||
                Objects.isNull(fieldValue)  ){
            return false;
        }
        return true;
    }


}
